package com.leessy.r229.server.http

import android.content.Context
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.util.Log
import com.alibaba.sdk.android.oss.model.PutObjectResult
import com.blankj.utilcode.util.ConvertUtils
import com.blankj.utilcode.util.FileUtils
import com.blankj.utilcode.util.TimeUtils
import com.blankj.utilcode.util.ZipUtils
import com.google.gson.Gson
import com.leessy.r229.App
import com.leessy.r229.BuildConfig
import com.leessy.r229.MService
import com.leessy.r229.config.Config
import com.leessy.r229.constants.Constants
import com.leessy.r229.kt.observeOnIo
import com.leessy.r229.kt.subscribeOnIo
import com.leessy.r229.kt.subscribeOnNew
import com.leessy.r229.kt.toJsonString
import com.leessy.r229.server.http.databean.ConfigData
import com.leessy.r229.server.http.databean.FaceLoadResultBean
import com.leessy.r229.server.http.databean.HeartBeatBean
import com.leessy.r229.server.http.databean.LogsDataBean
import com.leessy.r229.server.http.databean.RequestBean
import com.leessy.r229.server.http.databean.StatusBean
import com.leessy.r229.server.http.databean.TaskData
import com.leessy.r229.server.http.databean.Tasks
import com.leessy.r229.utils.AppUtil
import com.leessy.r229.utils.DevicesBootUtil
import com.leessy.r229.utils.DevicesUtil
import com.leessy.r229.utils.OtaUtil
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.disposables.Disposable
import io.reactivex.rxjava3.schedulers.Schedulers
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import okhttp3.Cache
import okhttp3.Call
import okhttp3.Callback
import okhttp3.Dns
import okhttp3.MediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody
import okhttp3.Response
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStream
import java.net.InetAddress
import java.net.UnknownHostException
import java.util.Calendar
import java.util.concurrent.TimeUnit
import kotlin.experimental.xor

/**
 * 后台任务处理
 * 定时请求心跳 返回任务列表
 */
object LoadTask {
    private val TAG = "LoadTask"
    private val mediaType = MediaType.parse("application/json")
    private val gson = Gson()

    private val period = if (BuildConfig.DEBUG) 30L else 60L

    private var disposable: Disposable? = null

    private var sn = ""
    private var firstStatus = false//开机启动至少上报一次状态
    var downloader: Disposable? = null
    var retryCount = 0


    fun creatRequesSerialNo(): String {
        if (sn.isNotBlank()) return sn
        val v = "020104${Constants.SN}"
        val bytes = ConvertUtils.hexString2Bytes(v)
        var x: Byte = 0
        for (bs in bytes) {
            x = x xor bs
        }
        val hex = ConvertUtils.bytes2HexString(byteArrayOf(x))
        sn = hex + v
        return sn
    }

    /**
     * 同步人脸数据 任务,第一次启动时间太快 ,商汤算法可能还没有初始化完成
     */
    fun startTask() {
//        if (BuildConfig.DEBUG) return
        if (BuildConfig.DEBUG) Config.heatbeatInterval = 10
        disposable?.dispose()
        disposable = Observable.interval(10, Config.heatbeatInterval.toLong(), TimeUnit.SECONDS)
            .observeOnIo().throttleFirst(5, TimeUnit.SECONDS)
            .filter {
                checkReboot()//定时重启检查
                Config.isNetwork()
            }
            .map {
//                val isDisposed = downloader == null || downloader!!.isDisposed
//                Log.d(TAG, "startTask --  $it   downloader isDisposed =$isDisposed")
                Log.d(TAG, "startTask heatbeatInterval心跳间隔=${Config.heatbeatInterval.toLong()} ")
                Log.d(TAG, "startTask --  $it   downloader isDisposed")
//                if (isDisposed) heartTask()
                heartTask()
                if (!firstStatus) {
                    uploadStatuts(null)
                }
                it
            }.subscribe({
                Log.d(TAG, "startTask: index $it")
            }, {
                it.printStackTrace()
                Log.d(TAG, "startTask: $it")
                startTask()//异常重新开始
            })
    }


    fun checkOtaStatu() {
        if (OtaUtil.isUpdate > 0 && Config.otaTaskId > 0) {
            uploaderTaskStatus(TaskData().apply {
                taskId = Config.otaTaskId
                taskType = 2 //ota
            }, "OTA 任务结束", OtaUtil.isUpdate == 1)
        }
    }

    private var sycn: Disposable? = null

    @Synchronized
    private fun heartTask() {
        sycn?.let {
            if (!it.isDisposed) {
                Log.d(TAG, "heartTask: 上一次数据还没有处理完！！")
                return/*上次的数据还在处理中 */
            }
        }
        //请求心跳，上传最后一次处理的任务taskid
        val create = RequestBody.create(mediaType, gson.toJson(createHeartJson()))
        sycn = HttpRetrofit.apiService().heartbeat(create).subscribeOnNew().map {
            Log.d(TAG, "heartTask: ${it.toString()}")
            if (it.isSuccess()) {
                //请求成功，解析是否有新的任务处理，任务id为0时强制执行，并且task 复位0
//                if (it.config != null) {
//                    config(it.config!!)
//                }

                println("=checkConfig=it.action=${it.action}==it.text=${it.text}")
                val lockupdated = Constants.deviceLockAction != it.action || Constants.deviceLockText != it.text

                Constants.deviceLockAction = it.action
                Constants.deviceLockText = it.text
                if (lockupdated){
                    MService.mService?.checkConfig()
                }

                if (it.tasks != null) {
                    task(it.tasks!!, it)
                }
                ///心跳成功后判断一次ota
                checkOtaStatu()
            }else{
                Constants.deviceLockAction = 0
            }
            return@map 0
        }.subscribe({

        }, {
            Constants.deviceLockAction = 0
            it.printStackTrace()
            Log.d(TAG, "heartTask: 异常 $it")
        })
    }

    //配置更新
    fun config(data: ConfigData) {
        if (data.heatbeatInterval in 10..3600) {
            Config.heatbeatInterval = data.heatbeatInterval
        }
        AppUtil.updateConfig(data)
        //重启时间
        if (!data.autoRestartAt.isNullOrEmpty()) {
            Config.autoRestartAt = data.autoRestartAt
        }
        //设备名称
        if (data.deviceName != Config.deviceName) {
            Config.deviceName = data.deviceName
            DevicesUtil.setDeviceName(Config.deviceName!!)
        }
        Config.systemlog = data.systemlog
        Config.autoRunApp = "${data.autoRunApp}"
        if (Config.otaDisable != data.otaDisable) {
            Config.otaDisable = data.otaDisable
            OtaUtil.initServerStatu()
        }
    }

    fun checkReboot() {
        if (System.currentTimeMillis() - Config.rebootTimes > 3660 * 1000) {//一个小时内不重启
            val r = Config.autoRestartAt?.replace(":", "")?.toLongOrNull() ?: -1
            if (r >= 0) {
                val n = TimeUtils.millis2String(System.currentTimeMillis(), "HHmmss").toLongOrNull()
                    ?: -1
                if (r / 100 == n / 100) {//在同一个时辰内
                    if (n > 0 && n - r > 0 && n - r <= Config.heatbeatInterval + 10) {//重启时间在心跳间隔内
                        Log.d(TAG, "checkReboot: 定时重启...")
                        Config.rebootTimes = System.currentTimeMillis()
                        DevicesBootUtil.reboot(App.app)
                    }
                }
            }
        }
    }

    fun task(datas: List<TaskData>, heartBeatBean: HeartBeatBean) {
        if (datas.size == 0) return
        Log.d(TAG, "task size =" + datas.size)
        for (data in datas) {
            when (data.taskType) {
                0 -> {
                    //上报设备状态
                    uploadStatuts(data)
                }

                1 -> {
                    var file = File(Constants.rootPath_Upgrade, "install_app.apk")
//                    downloadFile(data, file)
                    newDownloadFile(data, file)
                }

                2 -> {
                    var file = File(Constants.otaFile)
//                    downloadFile(data, file)
                    newDownloadFile(data, file)
                }

                3 -> {
                    if (data.data?.logType == 1) {
                        uploadFileLogcat(data)
                    } else if (data.data?.logType == 2) {
                        val delete = FileUtils.delete("${data.data?.path}")
                        Log.d(TAG, "task: delete file =$delete")
                        uploaderTaskStatus(data, "操作完成", delete)
                    } else if (data.data?.logType == 0) {
                        uploadFile(data) //上传一个指定路劲文件
                    }
                }

                4 -> {
                    uploaderTaskStatus(data, "操作完成", true)
                    Thread.sleep(600)
                    DevicesBootUtil.reboot(App.app)
                }

                5 -> {
                    AppUtil.uninstallApp("${data.data?.appPackageName}")
                    uploaderTaskStatus(data, "操作完成", true)
                    DevicesBootUtil.reboot(App.app)
//                    uploadFileLogcat(data)
                }

                6 -> {
                    val cfg = gson.fromJson(data.data!!.toJsonString(), ConfigData::class.java)
                    config(cfg)
                    uploaderTaskStatus(data, "更新配置成功", true)
                }
            }
            Thread.sleep(3000)
        }
    }


    private fun uploadFileLogcat(data: TaskData) {
        //删除之前的zip文件
        val file = File(Constants.rootPath_Log)
        val listFiles = file.listFiles()
        if (listFiles != null) {
            for (listFile in listFiles) {
                if (listFile.name.contains("zip")) FileUtils.delete(listFile)
            }
        }

        val filename = Constants.rootPath_Log +
                "/logcat_${TimeUtils.millis2String(System.currentTimeMillis(), "yyyyMMdd")}.zip"
        val zipFile = ZipUtils.zipFile(Constants.rootPath_Log + "/logcat/", filename)
        if (zipFile) {
            data.data?.path = filename
            data.maxLength = 1000//不限制大小
            uploadFile(data)
        }

    }

    private fun uploadStatuts(data: TaskData?) {
        val statusBean = StatusBean()
        statusBean.sn = creatRequesSerialNo()//DevicesUtil.getDeviceSN()
        statusBean.time = TimeUtils.millis2String(System.currentTimeMillis(), "yyyyMMddHHmmss")
        statusBean.mac = DevicesUtil.getEth0Mac()
        statusBean.wifimac = DevicesUtil.getWlanMac()
        statusBean.systemVer = DevicesUtil.getSystemVer()
        statusBean.memoryTotal = DevicesUtil.getMemoryTotal()
        statusBean.memoryAvailable = DevicesUtil.getMemoryAvailable()
        statusBean.ramTotal = DevicesUtil.getRamTotal()
        statusBean.ramUsed = DevicesUtil.getRamUsed()
        statusBean.iccid = "${Config.DEV_ICCID}"
        statusBean.IMSI = "${Config.DEV_IMSI}"
        statusBean.internalIP = "${Config.ipAddress}"
        statusBean.appVer = BuildConfig.VERSION_NAME
        statusBean.encipherChip = "${Config.checkEncipher}" == "OK"
//        statusBean.installedList = AppUtil.getAllUserPkgStr()
        statusBean.installedList = AppUtil.getAllAppDetailInfo()
        statusBean.heatbeatInterval = Config.heatbeatInterval
        statusBean.otaDisable = Config.otaDisable
        statusBean.deviceExpireDay = Config.deviceExpireDay


        // var networdStatus = 0//网络状态:  0没有网络  1 移动网络 2 WiFi网络 3 以太网
//设备当前通信方式(wired-有线 wireless-无线 cellular-蜂窝网)
        statusBean.commWay = when (Config.networdStatus) {
            1 -> "cellular"
            2 -> "wireless"
            3 -> "wired"
            else -> "none"
        }

//        getInstalledNonSystemApps(App.app)

//        Log.d(TAG,"=status=${gson.toJson(statusBean)}")
        val create = RequestBody.create(mediaType, gson.toJson(statusBean))
        val d = HttpRetrofit.apiService().status(create).subscribeOnNew().subscribe({
            if (it.isSuccess()) {
                firstStatus = true
                if (data != null) uploaderTaskStatus(data, "操作成功", true)
            } else {
                if (data != null) uploaderTaskStatus(data, "操作失败 code = ${it.code}")
            }
        }, {
            data?.let { uploaderTaskStatus(it, "操作失败") }
            it.printStackTrace()
        })

    }


    private fun getInstalledNonSystemApps(context: Context) {
        val packageManager: PackageManager = context.packageManager
        val packages: List<PackageInfo> = packageManager.getInstalledPackages(0)
        for (packageInfo in packages) {
            if ((packageInfo.applicationInfo.flags and android.content.pm.ApplicationInfo.FLAG_SYSTEM) != 0) {
                val appName = packageInfo.applicationInfo.loadLabel(packageManager).toString()
                val packageName = packageInfo.packageName
                val versionName = packageInfo.versionName
                println("系统应用名称: $appName")
                println("系统应用包名: $packageName")
                println("系统应用版本号: $versionName")
                println("-------------------")
            }else{
                val appName = packageInfo.applicationInfo.loadLabel(packageManager).toString()
                val packageName = packageInfo.packageName
                val versionName = packageInfo.versionName
                println("==非系统应用名称: $appName")
                println("==非系统应用包名: $packageName")
                println("==非系统应用版本号: $versionName")
                println("-------------------")
            }
        }
    }



    fun downloadFile(data: TaskData, file: File) {/*说明是那个版本下载的*/
        if (data.data == null || data.data!!.url?.isNullOrEmpty()) {
            uploaderTaskStatus(data, "操作失败：url错误")
            return
        }
        downloader?.let {
            if (!it.isDisposed()) {
                Log.d(TAG, "downloadFile: 有下载任务未完成，跳过")
                uploaderTaskStatus(data, "操作失败，有其他任务在执行")
                return
            }
        }
        Log.d(TAG, "downloadFile: 开始下载: $file   url=${data.data?.url}")
        downloader =
            HttpRetrofit.apiService().download("${data.data!!.url}")
                .subscribeOn(Schedulers.newThread())
                .map {
                    MService.mService?.showDownloader(0, data.taskType)
                    val contentLength = it.contentLength()
                    val contentType = it.contentType()
                    Log.d(TAG, "downloadFile 开始下载: $contentType    $contentLength")
//                    val write = FileIOUtils.writeFileFromIS(file, it.byteStream())
                    writeFile(contentLength, it.byteStream(), file, data)
                    Log.d(TAG, "downloadFile: iswrite 下载完成 write =$")
                    //执行安装操作
                    if (data.taskType == 1) {
                        if (data.data!!.length == FileUtils.getLength(file)) {
                            retryCount = 0
                            uploaderTasking(data, 100)
                            if (data.data!!.forced){
                                AppUtil.uninstallApp(data.data!!.appPackageName)
                            }
                            Thread.sleep(100)
                            val b = AppUtil.installApp(file, data.data!!.appPackageName)
                            Log.d(TAG, "downloadFile: install " + b)
                            uploaderTaskStatus(data, if (b) "操作成功" else "安装失败", b)
                            if (b && data.data!!.autorun) {
                                AppUtil.startApp(data.data!!.appPackageName)
                            }
                        } else {
                            uploaderTaskStatus(data, "操作失败，文件校验错误", false)
                        }
                    } else if (data.taskType == 2) {
                        if (data.data!!.length == FileUtils.getLength(file)) {
                            retryCount = 0
                            Config.otaTaskId = data.taskId
                            uploaderTasking(data, 100)
                            Thread.sleep(3000)
                            MService.mService?.closeDownloader()
                            if (!BuildConfig.DEBUG) OtaUtil.upgradeOta()
                        } else {
                            uploaderTaskStatus(data, "操作失败，文件校验错误", false)
                        }
                    }
                    data.taskId
                }.doFinally {
                    MService.mService?.closeDownloader()
                }
                .subscribe({
                    Log.d(TAG, "downloadFile: 执行完成 taskid= $it")
                    //没有异常下载完成了
//                fileUpgrade(file.absolutePath, true)
                }, {
                    it.printStackTrace()
                    retryCount++
                    Log.d(TAG, "downloadFile: 下载异常 #$it")
                    uploaderTaskStatus(data, "操作异常：${it.message}")


                    val message = if (it.message.isNullOrEmpty()) "操作异常" else it.message
                    Log.d(TAG, "downloadFile: 下载异常 message=${message}===hostException=${message?.indexOf("UnknownHostException")}")
//                    Log.d(TAG, "downloadFile: 下载异常 message=${message}")
                    if (message?.indexOf("UnknownHostException")!! > -1) {
                        Log.d(TAG, "downloadFile: 下载异常 重试==retryCount=${retryCount}")
                        if (retryCount < 3) {
                            //下载异常，延时5秒钟重新发起下载请求
                            Thread.sleep(5000)
                            downloadFile(data, file)
                        }
                    }

                })

    }


    private fun newDownloadFile(data: TaskData, file: File) {/*说明是那个版本下载的*/
        if (data.data == null || data.data!!.url?.isNullOrEmpty()) {
            uploaderTaskStatus(data, "操作失败：url错误")
            return
        }
        CoroutineScope(Dispatchers.IO).launch {
            MService.mService?.showDownloader(0, data.taskType)
            DownloadManager(App.app).downloadFile(data,file, object : DownloadManager.DownloadCallback {
                override fun onSuccess(file: File) {
                    MService.mService?.closeDownloader()
                    //执行安装操作
                    if (data.taskType == 1) {
                        if (data.data!!.length == FileUtils.getLength(file)) {
                            uploaderTasking(data, 100)
                            if (data.data!!.forced){
                                AppUtil.uninstallApp(data.data!!.appPackageName)
                            }
                            Thread.sleep(100)
                            val b = AppUtil.installApp(file, data.data!!.appPackageName)
                            Log.d(TAG, "downloadFile: install " + b)
                            uploaderTaskStatus(data, if (b) "操作成功" else "安装失败", b)
                            if (b && data.data!!.autorun) {
                                AppUtil.startApp(data.data!!.appPackageName)
                            }
                        } else {
                            uploaderTaskStatus(data, "操作失败，文件校验错误", false)
                        }
                    } else if (data.taskType == 2) {
                        if (data.data!!.length == FileUtils.getLength(file)) {
                            Config.otaTaskId = data.taskId
                            uploaderTasking(data, 100)
                            Thread.sleep(3000)
                            MService.mService?.closeDownloader()
                            if (!BuildConfig.DEBUG) OtaUtil.upgradeOta()
                        } else {
                            uploaderTaskStatus(data, "操作失败，文件校验错误", false)
                        }
                    }
                    data.taskId
                }

                override fun onError(message: String) {
                    Log.d(TAG, "downloadFile: 下载异常 #$message")
                    uploaderTaskStatus(data, "操作异常：${message}")
                    MService.mService?.closeDownloader()
                }

            })
        }
    }


    class DownloadManager(context: Context) {
        private val client: OkHttpClient = OkHttpClient.Builder()
            .connectTimeout(5, TimeUnit.SECONDS)
            .readTimeout(5, TimeUnit.SECONDS)
            .dns(CustomDns())
            .cache(Cache(context.cacheDir, 10 * 1024 * 1024)) // 10MB缓存
            .build()
        fun downloadFile(data: TaskData, outputFile: File, callback: DownloadCallback) {
            val request = Request.Builder().url(data.data!!.url).build()
            client.newCall(request).enqueue(object : Callback {
                override fun onFailure(call: Call, e: IOException) {
                    if (e is UnknownHostException) {
                        callback.onError("DNS解析失败: ${e.message}")
                    } else {
                        callback.onError("下载失败: ${e.message}")
                    }
                }
                override fun onResponse(call: Call, response: Response) {
                    if (!response.isSuccessful) {
                        callback.onError("服务器错误: ${response.code()}")
                        return
                    }

                    response.body().let { body ->
                        try {
                            var contentLength = body?.contentLength()
                            var contentType = body?.contentType()
                            Log.d(TAG, "downloadFile 开始下载: $contentType    $contentLength")
                            if (contentLength != null && body?.byteStream() != null) {
                                writeFile(contentLength, body?.byteStream(), outputFile, data)
                                Log.d(TAG, "downloadFile: iswrite 下载完成 write =$")
                                callback.onSuccess(outputFile)
                            }

//                            InputStream(body.byteStream()).use { inputStream ->
//                                FileOutputStream(outputFile).use { outputStream ->
//                                    val buffer = ByteArray(4096)
//                                    var bytesRead: Int
//                                    while (inputStream.read(buffer).also { bytesRead = it } != -1) {
//                                        outputStream.write(buffer, 0, bytesRead)
//
//                                    }
//                                    callback.onSuccess(outputFile)
//                                }
//                            }
                        } catch (e: IOException) {
                            callback.onError("文件写入失败: ${e.message}")
                        }
                    }
                }
            })
        }

        private class CustomDns : Dns {
            private val GOOGLE_DNS: List<InetAddress> = listOf(
                InetAddress.getByName("223.5.5.5"),
                InetAddress.getByName("223.6.6.6")
            )
            override fun lookup(hostname: String): List<InetAddress> {
                return try {
                    // 首先尝试系统DNS
                    Dns.SYSTEM.lookup(hostname)
                } catch (e: UnknownHostException) {
                    // 尝试备用DNS
                    try {
                        InetAddress.getAllByName(hostname).toList()
                    } catch (e2: UnknownHostException) {
                        // 最后尝试Google DNS
                        GOOGLE_DNS
                    }
                }
            }
        }
        interface DownloadCallback {
            fun onSuccess(file: File)
            fun onError(message: String)
        }
    }


//    class FileDownloader(private val dns: Dns = CachedDns()) {
//        private val client = OkHttpClient.Builder()
//            .dns(dns)
//            .connectTimeout(Duration.ofSeconds(15))
//            .build()
//
//        fun download(url: String, savePath: String, callback: (Result<File>) -> Unit) {
//            val request = Request.Builder().url(url).build()
//            client.newCall(request).enqueue(object : Callback {
//                override fun onFailure(call: Call, e: IOException) {
//                    callback(Result.failure(e))
//                }
//
//                override fun onResponse(call: Call, response: Response) {
//                    try {
//                        response.body?.use { body ->
//                            File(savePath).outputStream().use { output ->
//                                body.byteStream().copyTo(output)
//                                callback(Result.success(File(savePath)))
//                            }
//                        }
//                    } catch (e: Exception) {
//                        callback(Result.failure(e))
//                    }
//                }
//            })
//        }
//    }



    //{"config":{"deviceName":"","heatbeatInterval":180,"installationCtrl":true,"installationList":"",
// "appEnableCtrl":true,"appEnableList":"","deviceExpire":false,"deviceExpireMsg":"",
// "deviceLock":false,"deviceAutoLockDate":"","autoRestartAt":"03:00:00"},"tasks":[],
// "code":100,"msg":"ok","sn":"020104F6585D22398E","time":"202501041553096"}
    private fun createHeartJson(): RequestBean {
        val r = RequestBean()
//        var data = HeartbeatParamsBean()
//        data.mac = DevicesUtil.getEth0Mac()
//        data.wifimac = DevicesUtil.getWlanMac()
//
//        data.deviceName = DevicesUtil.getDeviceName()
//        data.systemVer = DevicesUtil.getSystemVer()
//
//        data.memoryTotal = DevicesUtil.getMemoryTotal()
//        data.memoryAvailable = DevicesUtil.getMemoryAvailable()
//        data.ramTotal = DevicesUtil.getRamTotal()
//        data.ramUsed = DevicesUtil.getRamUsed()
//
//        data.installedList = AppUtil.getAllUserPkgStr()
//        data.taskId = Config.taskId
//        data.ip = Config.ipAddress
//        data.ICCID = Config.DEV_ICCID
//        data.IMSI = Config.DEV_IMSI
//        data.IMEI = Config.DEV_IMEI
//
//        data.WiFiSignal = "${Config.signalIntensityFor4G}"
//        data.MobileSignal = "${Config.signalIntensityForWIFI}"

        r.sn = creatRequesSerialNo()//DevicesUtil.getDeviceSN()
        r.time = TimeUtils.millis2String(System.currentTimeMillis(), "yyyyMMddHHmmss")
//        r.config = data  //修改心跳不带config数据
        return r
    }

    private fun getWeek(): String {
        return "${Calendar.getInstance().get(Calendar.DAY_OF_WEEK)}"
    }

    private fun uploadResultStatus(resultBean: List<FaceLoadResultBean>) {
        if (resultBean.isEmpty()) return
        uploadResultStatus(FaceLoadResultBean().apply {
            clientID = resultBean.first().clientID
            models = resultBean
        })
    }

    //上报结果
    private fun uploadResultStatus(resultBean: FaceLoadResultBean) {
        try {
            val d = HttpRetrofit.apiService()
                .faceSyncTasks(RequestBody.create(mediaType, gson.toJson(resultBean))).execute()
            Log.d(TAG, "uploadResultStatus: 同步上报结果  body: ${d?.body()}")
        } catch (e: Exception) {
            Log.d(TAG, "uploadResultStatus: 同步上报结果  err: ${e}")
        }
    }


    fun uploadFile(data: TaskData) {
        val file = File("${data.data?.path}")
        if (!file.isFile) {
            uploaderTaskStatus(data, "找不到文件：${data.data?.path}")
            Log.d(TAG, "uploadFile: 参数错误 找不到文件*** " + data.data?.path)
            return
        }
        val length = file.length()
        val mb = length / 1024 / 1024
        if (length < 0 || mb > data.maxLength) {
            uploaderTaskStatus(data, "文件长度错误：${length}")
            Log.d(TAG, "uploadFile: 文件长度错误")
            return
        }
        val osspath = OssServerUtil.createFileName(file.name)
        val uploadFiletoOss = uploadFiletoOss(osspath, data.data?.path!!)
        if (uploadFiletoOss != null) {
            val r = RequestBean()
            var d = LogsDataBean()
            d.bucketName = Constants.bucketName
            d.objectName = osspath
            d.logFileSize = 0
            d.logType = data.data?.logType ?: 0
            d.taskId = data.taskId
//            data.fileCreateAt = 0
//            data.fileUpdateAt = 0
            r.sn = creatRequesSerialNo()//DevicesUtil.getDeviceSN()
            r.time = TimeUtils.millis2String(System.currentTimeMillis(), "yyyyMMddHHmmss")
            r.logs = arrayListOf(d)
            val create = RequestBody.create(mediaType, gson.toJson(r))
            sycn = HttpRetrofit.apiService().postfile(create).subscribeOnIo().subscribe({
                Log.d(TAG, "uploadFile: $it")
                if (it.isSuccess()) {
                    Config.taskId = data.taskId
                    uploaderTaskStatus(data, "执行成功", true)
                } else {
                    uploaderTaskStatus(data, "上传logs失败，code = ${it.code}")
                }
            }, {
                uploaderTaskStatus(data, "上传logs失败" + it.message)
                it.printStackTrace()
                Log.d(TAG, "uploadFile err : $it")
            })
        } else {
            uploaderTaskStatus(data, "上传文件到oss服务器失败")
        }
    }

    /**
     * 将输入流写入文件
     * @param inputString
     * @param file
     */
    private fun writeFile(lenght: Long, inputString: InputStream, file: File, data: TaskData) {
        if (file.exists()) {
            file.delete()
        }
        var fos: FileOutputStream? = null
        fos = FileOutputStream(file)

        var readLength = 0L
        val b = ByteArray(1024 * 100)//100k
        var len: Int
        var p = 0
        while (inputString.read(b).also { len = it } != -1) {
            readLength += len
            fos.write(b, 0, len)
            val pp = (readLength.toDouble() / lenght * 100F).toInt()
            if (pp != p) {
                p = pp
                MService.mService?.showDownloader(p)
                Log.d(TAG, "writeFile: 下载进度 :" + p)
                uploaderTasking(data, p)
            }
//            publishSubjectProgress.onNext((readLength.toDouble() / lenght * 100F).toInt())
        }
        inputString.close()
        fos.close()
    }

    /*上传消费机记录<图片>*/
    fun uploadFiletoOss(osspath: String, file: String): PutObjectResult? {
        try {
            try {
                val putObject = OssServerUtil.putObject(osspath, file)
                Log.d(TAG, "uploadRecord: oss file ${putObject}")
                return putObject

            } catch (e: Exception) {
                e.printStackTrace()
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return null
    }

    private var taskTime = 0L//执行中任务上传时间，最快10秒中一次

    //上报任务处理中状态
    fun uploaderTasking(taskData: TaskData, progress: Int) {
        if (progress < 100 && System.currentTimeMillis() - taskTime < 10000) return
        taskTime = System.currentTimeMillis()
        val tasks = Tasks()
        tasks.taskId = taskData.taskId
        tasks.taskType = taskData.taskType
        tasks.taskError = "任务执行中"
        tasks.taskStatus = 10
        tasks.progress = progress
        val r = RequestBean()
        r.sn = creatRequesSerialNo()//DevicesUtil.getDeviceSN()
        r.time = TimeUtils.millis2String(System.currentTimeMillis(), "yyyyMMddHHmmss")
        r.tasks = arrayListOf(tasks)

        val create = RequestBody.create(mediaType, gson.toJson(r))
        sycn = HttpRetrofit.apiService().heartbeat(create).subscribeOnNew().map {
            Log.d(TAG, "uploaderTaskStatus: ${it.isSuccess()}")
            return@map 0
        }.subscribe({

        }, {
            it.printStackTrace()
            Log.d(TAG, "uploaderTaskStatus: 异常 $it")
        })
    }

    //上传任务处理状态
    fun uploaderTaskStatus(taskData: TaskData, msg: String, status: Boolean = false) {
        val tasks = Tasks()
        tasks.taskId = taskData.taskId
        tasks.taskType = taskData.taskType
        tasks.taskError = msg
        tasks.taskStatus = if (status) 1 else 2
        val r = RequestBean()
        r.sn = creatRequesSerialNo()//DevicesUtil.getDeviceSN()
        r.time = TimeUtils.millis2String(System.currentTimeMillis(), "yyyyMMddHHmmss")
        r.tasks = arrayListOf(tasks)

        val create = RequestBody.create(mediaType, gson.toJson(r))
        sycn = HttpRetrofit.apiService().heartbeat(create).subscribeOnNew().map {
            Log.d(TAG, "uploaderTaskStatus: ${it.isSuccess()}")
            return@map 0
        }.subscribe({

        }, {
            it.printStackTrace()
            Log.d(TAG, "uploaderTaskStatus: 异常 $it")
        })
    }
}